#include "In8Bala.h"

In8Bala_T* In8Bala_t;

//************************************
// Method:    	CALCU_SAMA					//< SAMA运算函数
// Programmer:  duan
// Time:		2019/06/24
// Returns:   	bool						//< 成功：true；失败：false
// Parameter: 	Model_Base_t * arg			//< 模块参数结构体指针
// Parameter: 	float dt					//< 运算周期
// Parameter: 	bool * DI					//< 数字量输入值数组指针
// Parameter: 	bool * DO					//< 数字量输出值数组指针
// Parameter: 	bool * AI					//< 模拟量输入值数组指针
// Parameter: 	bool * AO					//< 模拟量输出值数组指针
//************************************
bool CALCU_SAMA(In8Bala)(Model_Base_t* arg, float dt, bool* DI, bool* DO, float* AI, float* AO)
{
	/****************变量定义区开始**************/

	int i = 0;
	int j = 0;
	float tmpfloat;
	float Tracc = 0;
	int PointAUTO_Num = 0;
	int PointValid_Num = 0;
	/*<<<<<定义输入变量>>>>>*/
	float AI_Value;
	float TR_Value[8];
	bool TS_Sta[8];

	/*<<<<<定义输出变量>>>>>*/
	float AO_Value;
	bool DO_Value;

	/*<<<<<定义参数变量>>>>>*/
	float HL;
	float LL;
	In8Bala_OutMode Out_Mode;						//< duan 日后做成枚举类型
	
	/*<<<<<定义中间变量>>>>>*/
	bool* AIfLink[9];					//< 记录模拟量输入的有效测点
	bool* DIfLink[8];					//< 记录数字量输入的有效测点
	float* LinkAV[8];

	/****************变量定义区结束**************/

	NAME(In8Bala)* Obj = (NAME(In8Bala)*)arg;

	/****************变量赋值**************/
	/*<<<<<输入变量赋值>>>>>*/
	AI_Value = AI[0];

	for (i = 0; i < 8; i++)
	{
		TR_Value[i] = AI[i + 1];
		TS_Sta[i] = DI[i];
	}

	/*<<<<<参数变量赋值>>>>>*/
	HL = Obj->Par.HL;
	LL = Obj->Par.LL;
	Out_Mode = Obj->Par.Out_Mode;

	/*<<<<<中间变量赋值>>>>>*/
	for (i = 0; i < 9; i++)
		AIfLink[i] = &(Obj->Sta.AIfLink[i]);

	for (i = 0; i < 8; i++)
	{
		DIfLink[i] = &(Obj->Sta.DIfLink[i]);
		LinkAV[i] = &(Obj->Sta.LinkAV[i]);
	}

	/**************变量赋值结束************/

	/********************************************/
	/**************算法功能实现开始**************/
	/********************************************/
	for (i = 1; i < 9; i++)
	{
		if (AIfLink[i][0] == true && DIfLink[i - 1][0] == true)				//< 所有8对中输入（跟踪值、跟踪开关）不为NULL的测点
		{
			LinkAV[PointValid_Num][0] = TR_Value[i - 1];
			PointValid_Num++;

			if (TS_Sta[i - 1] == true)										//< 手动点
				Tracc += TR_Value[i-1];
			else
				PointAUTO_Num++;											//< 自动点个数计数
		}
	}

	for (i = 0; i < PointValid_Num; i++)									//< LinkAV[j][0]中的值由小到大排序
	{
		for (j = 0; j < PointValid_Num - 1 - i; j++)
		{
			if (LinkAV[j][0] > LinkAV[j + 1][0])
			{
				tmpfloat = LinkAV[j][0];
				LinkAV[j][0] = LinkAV[j + 1][0];
				LinkAV[j + 1][0] = tmpfloat;
			}

		}

	}

	if (PointAUTO_Num != 0)
	{
		AO_Value = (PointValid_Num * AI_Value - Tracc) / PointAUTO_Num;
		DO_Value = false;
	}
	else																		//< 所有信号跟踪即全部为手动点																			
	{
		DO_Value = true;

		if (PointValid_Num != 0)
		{
			if (Out_Mode == Average_Value)
				AO_Value = Tracc / PointValid_Num;
			else if (Out_Mode == Max_Value)
				AO_Value = LinkAV[PointValid_Num - 1][0];
			else
				AO_Value = LinkAV[0][0];

		}
	}

	if (AO_Value > HL)
		AO_Value = HL;
	if (AO_Value < LL)
		AO_Value = LL;

	/********************************************/
	/**************算法功能实现结束**************/
	/********************************************/
	
	/****************运算结果输出**************/
	AO[0] = AO_Value;
	DO[0] = DO_Value;

	/**************运算结果输出完毕************/
	return true;
}



//************************************
// Method:    	BCPARA						//< 广播SAMA参数变量函数（无参数需要广播的模块直接将BCPara函数设置为NULL即可）
// Programmer:  duan
// Time:		2019/06/24
// Returns:   	int							//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg			//< 模块参数结构体指针
// Parameter: 	void ** Data				//< 广播SAMA参数的数据包的指针
//************************************
int BC_PARA(In8Bala)(Model_Base_t* arg, void** Data)
{
	NAME(In8Bala)* Obj = (NAME(In8Bala)*)arg;
	BC_PARA_PUBLIC(Obj);
	return 0;
}



//************************************
// Method:    	BAK_STA						//< 备份SAMA运算中间参数
// Programmer:  duan
// Time:		2019/06/24
// Returns:   	int							//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg			//< 指定模块类型链表的指针
// Parameter: 	void ** Data				//< 存放数据包当前指针位置的地址
//************************************
int BAK_STA(In8Bala)(Model_Base_t* arg, void** Data)
{
	NAME(In8Bala)* Obj = (NAME(In8Bala)*)arg;
	BAK_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	ANA_STA						//< 解析备份的SAMA运算中间参数
// Programmer:  duan
// Time:		2019/06/24
// Returns:   	int							//< 成功：返回解析字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg			//< 模块参数结构体指针
// Parameter: 	void ** Data				//< 存放数据包当前指针位置的地址
//************************************
int ANA_STA(In8Bala)(Model_Base_t* arg, void** Data)
{
	NAME(In8Bala)* Obj = (NAME(In8Bala)*)arg;
	ANA_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	CHANGE_PAR				//< 在线修改模块参数函数
// Programmer:  duan
// Time:		2019/06/24
// Returns:   	int						//< 读取字节长度计数值
// Parameter: 	Model_Base_t* arg		//< 指定模块类型链表的指针
// Parameter: 	void** Data				//< 存放数据包当前指针位置的地址
//************************************
int CHANGE_PAR(In8Bala)(Model_Base_t* arg, void** Data)
{
	int _iLen = 0;
	MEMREAD(((NAME(In8Bala)*)arg)->Par, Data[0]);
	return _iLen;
}



//************************************
// Method:    	INIT_STAPAR					//< 初始化模块运算中间参数
// Programmer:  duan
// Time:		2019/06/24
// Parameter: 	Model_Base_t* arg			//< 模块参数结构体指针
//************************************
void INIT_STAPAR(In8Bala)(Model_Base_t* arg)
{
	int i;

	NAME(In8Bala)* name = (NAME(In8Bala)*)arg;
	/****************初始化中间变量结构体**************/
	memset(&(name->Sta), 0, sizeof(name->Sta));
	/**************初始化中间变量结构体结束************/

	/****************对中间变量结构体的相关参数进行赋值**************/
	for (i = 0; i < name->Base.IO_Num.AI_Num; i++)
	{
		if (name->Base.In.AI_Pin_ID[i] > 0)
		{
			name->Sta.AIfLink[i] = true;
		}
	}
	for (i = 0; i < name->Base.IO_Num.DI_Num; i++)
	{
		if (name->Base.In.DI_Pin_ID[i] > 0)
		{
			name->Sta.DIfLink[i] = true;
		}
	}
	/**************对中间变量结构体的相关参数进行赋值结束************/
}
